Scite Ext Man

lua-users home
wiki

스크립트들을 함께 사이 좋게 실행하는 법

최근 버전(2006-11-10)에서는 리눅스 버전에서의 심각한 버그가 교정되었고 좀 더 튼튼한 체계를 사용하여 입력된 줄이 편집판에 있는지 아니면 출력판에 있는지 결정한다. 또한 '스크립트 재적재' (Ctrl+Shift+R)로 extman이 제어하는 루아 스크립트를 재적재할 수 있다. 예제들이 더 추가되었다: * prompt.lua는 루아 프롬프트로 간단한 상호대화를 제공한다. * select_string.lua는 더블-클릭으로 전체 문자열 (또는 주석)을 선택할 수 있다. * select_block.lua는폴드 라인 옆의 여백을 클릭하면 블록을 선택할 수 있다.

extman은 Files:wiki_insecure/editors/SciTE/extman.lua에 있고; 예제와 코드는 Files:wiki_insecure/editors/SciTE/extman.zip에 있다; 완전히 루아로 작성되었으며 최신 SciTE 배포본과 잘 작동한다.

SciTE Lua 인터페이스는 아주 강력하다. 그러나 현재 무거운 스크립트들을 서로 '사이 좋게' 실행시킬 방법이 없다. SciteBufferSwitch를 생각해 보자; OnOpen,OnSwitchFile 그리고 OnUserListSelection 처리자는 모두 버퍼 변화를 추적하도록 오버라이드되고 드롭-다운 버퍼 리스트를 보여준다. 그런 스크립트는 이런 이벤트들을 감시할 필요가 있는 다른 스크립트에 방해가 된다.

extman을 사용하면, 이 스크립트는 다음과 같이 보인다 (함수 buffer_switch는 똑같다)

scite_OnOpen(buffer_switch)
scite_OnSwitchFile(buffer_switch)

scite_Command 'Switch Buffer|do_buffer_list|Ctrl+J'

function do_buffer_list()
     scite_UserListShow(buffers,2,scite.Open)
end

(extman 최신 버전은 OnOpenSwitch도 지원한다. 열거나 버퍼를 전환하여 파일이 활성화될 때 호출된다 switch_buffers.lua 예제를 한 번 보자)

내부적으로, extman은 처리자 리스트를 유지한다. 예를 들면, scite_OnOpenOnOpen이 호출할 처리자 리스트에 함수를 추가한다. 이제 또다른 스크립트가 OnOpen 이벤트를 완벽하게 청취할 수 있다. 충돌을 일으키지 않는다. 비슷하게scite_OnChar, scite_OnSave, 등등의 이벤트가 있다 - OnUserListSelection만 제외되는데, 다르게 처리되기 때문이다.

확장 이벤트

표준 SciTE Lua 이벤트 말고도, extman은 OnWord, OnEditorLine 그리고 OnOutputLine을 제공한다. 기본 이벤트들 위에 건설되었고 편의를 위해 포함되었다.

다음은 extman을 위하여 재작성된 '게으른' 단어 교체 예제이다. OnWord 처리자는 테이블을 받는다. 필드는 word, startp, endp, ch로 구성되는데 각각 발견된 단어, 그의 최초 위치, 마지막 위치, 그리고 그 단어 뒤에서 바로 발견된 문자이다.

function on_word(w)
  local subst = word_substitute(w.word)
  if subst ~= w.word then
         editor:SetSel(w.startp-1,w.endp-1)
         local was_whitespace = string.find(w.ch,'%s')
         if was_whitespace then
            subst = subst..w.ch
         end
         editor:ReplaceSel(subst)
         local word_end = editor.CurrentPos
         if not was_whitespace then
            editor:GotoPos(word_end + 1)
         end
      end
end  

scite_OnWord(on_word)

OnOutputLine은 오직 줄이 출력판에 타자될 경우에만 촉발된다. 다음은 간단하지만 SciTE용으로 효과적인 루아 콘솔이다:

 local prompt = '> '
 print 'Scite/Lua'
 trace(prompt)
  
 scite_OnOutputLine (function (line)
   local sub = string.sub
   if sub(line,1,2) == prompt then
        line = sub(line,3)
    end	
    if sub(line,1,1) == '=' then
        line = 'print('..sub(line,2)..')'
    end    
    local f,err = loadstring(line,'local')
    if not f then 
      print(err)
    else
      local ok,res = pcall(f)
      if ok then
         if res then print('result= '..res) end
      else
         print(res)
      end      
    end
    trace(prompt)
    return true
end)

OnEditorLine는 비슷한 이벤트이다. 사용자가 편집판에 줄을 입력할 경우에 일어난다는 점만 제외하고 말이다. 한 가지 주요한 차이점은 절대로 정상적인 문자 처리를 간섭하지 않는다는 것이다. 타자되는 선언 등등을 얼마든지 추적 유지할 수 있다. 다음 예제는 상당히 이상하지만, 어떻게 단축키를 연산에 묶을 수 있는지 보여준다.

 scite_Command 'AltX|do_altx_commands|Alt+X'

 function do_altx_commands()
    editor:BeginUndoAction()
    scite_OnChar('once',function (ch)
       editor:EndUndoAction()
       editor:Undo()
       if ch == 's' then
          print('ess')
       elseif ch == 'f' then
          editor:BeginUndoAction()
          scite_OnEditorLine(handle_line)
        end
       return true
    end)
  end

Alt+X를 타자하면, 이 함수는 한번-실행 OnChar 처리자를 설치한다. 오직 's' 또는 'f'에 관심이 있지만, 언제나 눌린 다음 문자를 '먹어 치운다'. Emacs 사용자는 그런 키 조합을 상당히 자연스럽다고 여기고, 아마도 Alt+Ctrl+Shift 조합보다 더 쉽게 타자할 것이다. OnChar는 특수 문자를 무시한다. 그래서 기호와 구두점으로 제한된다. (내 손가락은 Borland 환경에서 Ctrl+Q 다음에 숫자를 누르면 표식이 이동한다는 것을 여전히 기억한다 - SciteNumberedBookmarks 참조).

Alt+X 다음에 'f'를 누르면 사용자가 버퍼에 파일이름을 입력할 수 있다! 파일이름은 editor:Undo에 의해 즉시 제거된다 그리고 그 파일이 열린다.

 local function handle_line(line)
    editor:EndUndoAction()
    editor:Undo()
    scite_OnEditorLine(handle_line,'remove')
    scite.Open(line)	  
 end

편의 함수

extman는 몇가지 유용한 편의 함수를 제공한다. (파일 접근 같은) 어떤 경우 루아 라이브러리에 없는 기능을 보완한다. (예를 들면) SciTE에 lfs (Lua File System)가 포함되어 있으면, 사용자는 구현이 바뀌더라도 계속 scite_Files을 사용할 수 있다.

scite_UserListShow(list,start,fn)는 간편하게 Scintilla 사용자 리스트에 접근하는 방법이다 - 사용자 리스트는 적절하게 가른 문자열 등등으로 구성된다. 리스트에 시작 지표를 지정할 수 있다 - 여기에서는 현재 버퍼를 보여주지 않기 위해 사용했다.

scite_GetProp(key,default)props 의사-테이블을 살짝 감싼 래퍼이다. key 특성이 존재하지 않으면, props[key]는 nil이 아니라 빈 문자열을 돌려준다; default가 지정되지 않으면, 그 특성이 존재하지 않을 경우 이 함수는 실제로 nil을 돌려준다.

scite_Files(mask)는 path+mask에 있는 모든 파일을 돌려준다 (예, "d:/downloads/scite_lua/*.lua" - 정사선은 윈도우즈에서도 허용된다). SciteOther 라이브러리가 발견되면, 조용한 Execute를 사용하고, 그렇지 않으면 os.execute를 사용한다.

scite_FileExists(f)는 읽기를 위해 파일을 열 수 있으면 참을 돌려준다.

scite_dofile(f)dofile과 비슷하다. 단, 언제나 SciTE의 기본 홈에 상대적으로 파일을 적재하고, 조용하게 실패한다.

scite_Command(cmds)는 루아 함수를 도구 메뉴 아이템과 단축키에 연계하는데 아주 유용한 함수이다. 거기에 문자열을 건네든가, 아니면 문자열 리스트를 건넨다; 문자열을 형태가 <name>|<function>|<shortcut>인데, 여기에서 <shortcut>은 선택적이다.

설치와 초기화

폴더 이름을 유지하면서 파일을 SciTE 디렉토리에 풀자. Extman은 메인 루아 시작 스크립트가 목표이다 (물론 다른 곳에 두어도 된다)

ext.lua.startup.script=$(SciteDefaultHome)/extman.lua

시작하면, 기본 홈 디렉토리인 scite_lua 디렉토리 안에서 확장자가 .lua인 모든 파일을 찾아본다. ext.lua.directory로 다른 곳에 배치할 수도 있다.

이 파일들이 적재되므로 그 디렉토리에 extman.lua를 *두지 않아도 된다*! scite_Command를 호출하여 함수들을 등록할 기회가 있다. 미리 다른 스크립트도 적재할 수도 있다. 그래서 scite_require()가 추가되었다. 이 함수로 파일을 명시적으로 적재하면, extman은 그 파일이 적재되었다고 간주한다.

스크립트가 선택적으로 extman을 사용하도록 만드는 방법

아래의 코드는 OnChar에 대하여 루아 확장이 선택적으로 extman을 사용할 수 있다. extman-가능한 스크립트가 extman 없이도 여전히 잘 작동하도록 만든다.

먼저 처리자가 이미 존재하는지 살펴본다. 다음으로, scite_OnChar 같은 extman 함수가 없으면, 아주 간단한 교체가 만들어진다. 물론, 이렇게 extman을 테스트하는 것은 증명된 방법은 아니다. 나머지 코드는 그러면 아무 일도 없는 것처럼 extman 함수를 활용할 수 있다. 간단한 scite_OnChar 함수는 오직 처리자 하나만 다룰 수 있다; 더 복잡한 것은 예상하시겠지만 extman을 설치해야 한다.

if OnChar and not scite_OnChar then
  error("처리자를 여러 개 사용하고 싶다면 extman을 사용하세요")
elseif not scite_OnChar then
  local _OnChar
  scite_OnChar = function(f, remove)
    if remove then _OnChar = nil else _OnChar = f end
  end
  OnChar = function(c) if _OnChar then return _OnChar(c) end end
end

--SteveDonovan

사용자 주석

Extman은 훌륭하다. 그렇지만 scite가 scite_temp1 파일을 만들어 내는 곳을 통제하고 싶다. 보통 한 번 코드를 만들면 주석을 제거한 다음 extman에 방향전환해서 미리 만들어진 그 파일이 scite 실행 파일이 존재하는 디렉토리에 열리도록 만든다.

extman.zip에 따라오는 switch_headers.lua를 시험해 보려고 했다. SciTE 1.74를 사용했는데 문제가 있었다. 다음 줄을 바꾸어야 했다. 다음을:

   for i,v in list do
다음으로:
   for i,v in pairs(list) do
그리고 다음을:
   for i,ext in extensions do
다음으로 바꾸어야 했다:
   for i,ext in pairs (extensions) do


다음은 (diff을 사용해 만든) 패치이다. switch_buffers.lua가 제목없는 탭을 제거한다 (버퍼 리스트에서 빈 줄):
9a10
>    if string.find(f,'[\\/]$') then return end
11a13
>   if (f ~= "") then
20a23
>   end
30c33,35
<      scite_UserListShow(buffers,2,scite.Open)
---
>    if (table.getn(buffers) > 0) then
>      scite_UserListShow(buffers,1,scite.Open)
>    end


윈도우즈에서 문제를 만났다. scite_Files*.lua에 대하여 test.luatest.lua~에 모두 부합했고 둘 모두 적재했기 때문이다 (뒤의 파일이 앞의 파일을 오버라이드한다). 뒤의 파일은 Emacs가 저장한 임시 백업 사본이었다. 그리고 왜 편집한 test.lua를 적재했는데 아무 효과도 미치지 않는지 알아내는데 시간이 좀 걸렸다. 윈도우즈에서는 dir *.*을 사용하여 한 디렉토리의 모든 파일에 일치시키고 다음 그 리스트를 FileGlob에 있는 globtopattern 함수를 사용하여 걸러내기를 제안하는 바이다.

어쨌든, SciteDebug [1]는 extman.lua의 scite_Files을 다르게 구현한다. scite_Popen이 호출되는데, 사용가능성에 따라 spawner.popen 또는 os.execute를 선택적으로 래핑한다. 그 목적이 무엇인지 잘 모르겠지만, 이 함수를 호출할 때 순간적으로 나타나는 DOS 명령어 창을 피하기 위한 것 같다. (적어도 내가 시험해 볼 때는 그랬다). extman.lua의 두 버전이 합쳐지면 유용할 것 같다. --DavidManura


자동 연속 주석

다음은 연속 주석을 자동화하는 스크립트이다!

../scite_lua/ 폴더에 <filename>.lua으로 저장하고 SciTE를 재시작하자. (플랫폼에 상관없으리라 믿는다!)

--auto_continue_comments.lua

--다음 참조 테이블에서 (나중에) 올바른 줄끝(eol) 표식을 결정한다
local eol_tbl = {[0]="\r\n", [1]="\r", [2]="\n"}

function auto_continue_comment(line)

    -- 여러줄 주석 계속
    local multi = line:match("^(%s*)==%s*$")
    if multi then --줄에 "=="이 있다, 여러줄 주석을 시작한다
        local eol = eol_tbl[editor.EOLMode]
        editor:BeginUndoAction()
            editor:LineUp()
            editor:LineDelete()
            editor:AddText("--[=[" .. eol .. eol .. "--]=]" .. eol)
            editor:LineUp(); editor:LineUp()
            editor:AddText(multi)
        editor:EndUndoAction()

    -- 블록 주석 계속
    elseif line:find("^%s*%-%-%s*$") then --줄이 오직 '--'이다, 주석을 끝낸다
        editor:LineUp()
        editor:LineDelete()
    elseif line:find("^%s*%-%-") then --줄이 주석이다, 자동으로 주석을 계속한다
        editor:AddText("-- ")
    end

    return false --다른 메쏘드들이 이벤트에 반응하도록 허용한다
end

--extman에 처리자를 등록한다
scite_OnEditorLine(auto_continue_comment)

'--' 다음에 텍스트를 타자하다가, 엔터를 치면, 다음 줄에 '--'가 벌써 삽입된다! 원하지 않으면, 그냥 엔터를 한 번 더 치면 사라진다! '=='을 타자하고 엔터를 치면 여러줄 주석이 만들어지고 캐럿이 그 안에 위치한다! 영감을 주신 SirAlaran?에게 감사드린다. 샘플 세션은 아래를 보자. --PeterMacDonald

-- <- 다음에 텍스트가 오면 블록 주석을 시작한다
-- 줄이 오직 "--"일 때까지 계속한다

	-- 탭이나 스페이스가 "-- some text" 앞에 있으면,
	-- 다음과 같이, 블록 주석 들여쓰기가 시작된다!

--[=[
줄에 다음과 같이 "=="를 입력하면:
==
다음과 같이 여러줄 주석이 시작된다!
--]=]

--[=[
	탭이나 스페이스가 "==" 앞에 있으면
	다음과 같이 여러줄 주석이 들여쓰기 된다!
--]=]


(사용자 주석 끝)
FindPage · RecentChanges · preferences
edit · history
Last edited July 24, 2010 4:00 pm GMT (diff)